[an error occurred while processing this directive]
[an error occurred while processing this directive]


Будильник для Проводника

Александр Захарченко

az13@mailru.com

Редкая ситуация вызывает у пользователей Windows столь же сильные эмоции как исчезновение панели задач. Речь, конечно, не о том, что она может автоматически убираться с экрана, освобождая место окнам прикладных программ. Нет, панель задач (taskbar), а вместе с ней и рабочий стол (desktop), могут исчезнуть в результате системной ошибки. Со всплывающим экраном, гласящим, что программа <имярек> выполнила недопустимую операцию и будет закрыта, сталкивались все. И все знают, что остается только закрыть злосчастную программу и запустить ее снова. Но в таком же положении может оказаться и Проводник (Explorer), который как раз и обеспечивает функционирование панели задач. Закрыть-то он закроется, а откуда его запускать, ежели кнопки "Пуск" нет в наличии? Перегружаться? А если осталась работать задача, которую жалко прерывать?

В принципе, предполагается, что Проводник закрыть нельзя. Если воспользоваться трехклавишной комбинацией Ctrl+Alt+Del и, добравшись до окна "Завершение работы программы", попытаться отключить Explorer, то он тут же автоматически перезагрузится. Гарантией автоперегрузки оболочки служит ключ Реестра HKLM\Software\Microsoft\Windows\CurrentVersion\Winlogon, его строковый параметр "AutoRestartShell" должен быть 1. Но аварийные ситуации Windows всегда вносят свои коррективы в замыслы разработчиков. Завершая работу по критической ошибке, Проводник внезапно уносит с собой почти все способы диалога между пользователем и операционной системой (ОС). Исчезают также значки с рабочего стола и мышь теряет свою функциональность за пределами сохранившихся окон прикладных программ. Правда Windows все же реагирует на Alt+Tab (переключение между задачами) и Ctrl+Alt+Del, но ведь командной строки в окне Task Manager'а не предусмотрено!

Проводник работает с множеством динамических библиотек (dll). У себя я насчитал 35-40 постоянно загруженных dll-файлов к которым обращается Explorer. Неподходящая замена системных библиотек или добавление новых dll, содержащих ошибки, может вызвать полный крах Windows. В более легком варианте возможны только локальные проявления в виде отказов отдельных программ, среди которых Проводник ничем не лучше.

Если в случае такого отказа остается хотя бы одна программа с командной строкой (Windows Commander, окно сеанса DOS и т.д.), то для возврата в приемлемое состояние достаточно набрать команду explorer. На крайний случай хватит окна Internet Explorer'а (IE). Используя выпадающее меню в строке Адрес можно добраться до папки C:\Windows (или как вы там ее назвали при установке) и запустить explorer.exe. Более продвинутые пользователи смогут, например, соорудить макрос в Word'е или другом приложении MS Office и запустить Проводник, используя функцию Shell("explorer.exe"). CorelDraw, помимо своего языка скриптов - диалекта BASIC'а, теперь предоставляет доступ к VBA. Поэтому вышеизложенное относится и к нему. Аналогичный способ можно применить также в интегрированных средах разработки для любого языка.

Находясь во FrontPage 2000 нужно выбрать File->Preview in Browser для доступа к окну IE. В другом редакторе возможно придется набирать скрипт:

<script language=VBScript>
Dim Shell
Set Shell = CreateObject("WScript.Shell")
Shell.Run "explorer.exe"
Set Shell = Nothing
</script>

и переходить в режим предварительного просмотра.

Если же вы не используете IE и активным осталось окно другого browser'а, то в нем (как, впрочем и в IE) можно перейти в режим HTML, вставить туда вышеприведенный скрипт, сохранить страницу и обновить ее - Проводник снова радует глаз.

Для самых неприятных случаев, когда остаются только программы не имеющие возможности запускать процессы по выбору, можно создать маленькую программку-будильник:

#include <windows.h>
#define tclass "ClockExplorer123_az13"

#include <tlhelp32.h>

char *ac1="EXPLORER.EXE";

//Поиск Проводника среди активных процессов
BOOL IsExplorerActive(void) {
HANDLE hS=NULL, pH=NULL;
PROCESSENTRY32 proc;

hS = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hS == NULL) {
//Ошибка инициализации, предположим отсутствие Explorer'а, хуже не будет
   return FALSE;
}
proc.dwSize=sizeof(PROCESSENTRY32);
//Поиск Explorer'а среди исполняющихся процессов
if (Process32First(hS,&proc)) {
do {
if (strstr(proc.szExeFile,ac1) != NULL) {
//Explorer активен
if ((pH = OpenProcess(SYNCHRONIZE, TRUE, proc.th32ProcessID)) != NULL) {
   CloseHandle(pH);
   CloseHandle(hS);
   return TRUE;
}
}
} while (Process32Next(hS,&proc));
}
//Explorer не обнаружен
CloseHandle(hS);
return FALSE;
}

BOOL InitApp(HINSTANCE hInst);
BOOL InitInst(HINSTANCE hInst, UINT Cmd);
LRESULT CALLBACK WinProcMain(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);

int PASCAL WinMain(HINSTANCE hIns, HINSTANCE hpInst, LPSTR lpszComLine, int cmdShow) {
MSG msg;

//Окно программы остается скрытым
cmdShow = SW_HIDE;
// cmdShow = SW_SHOW;
if (!InitApp(hIns)) return(FALSE);
if (!InitInst(hIns,cmdShow)) return(FALSE);
while (GetMessage(&msg,NULL,0,0)) {
   TranslateMessage(&msg);
   DispatchMessage(&msg);
}
return(msg.wParam);
}

BOOL InitApp(HINSTANCE hInst) {
WNDCLASS wc;

wc.style = 0;
wc.lpfnWndProc = WinProcMain;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = HBRUSH(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = tclass;
return (RegisterClass(&wc));
}

BOOL InitInst(HINSTANCE hInst, UINT Cmd) {
HWND hwnd;

hwnd = CreateWindow(
tclass,
"Clock123_az13",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInst,
NULL);
if (!hwnd) return(FALSE);
ShowWindow(hwnd,Cmd);
return(TRUE);
}

LRESULT CALLBACK WinProcMain(HWND hwnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {

switch (uMsg) {
case WM_DESTROY:
if (!IsExplorerActive()) {
//Запуск Explorer'а
   WinExec(ac1,SW_SHOW);
//Перезапуск самой себя
   WinExec(GetCommandLine(),SW_HIDE);
}
PostQuitMessage(0);
break;
default:
return(DefWindowProc(hwnd, uMsg, wParam, lParam));
}
return(0);
}

Для компиляции использовался VC++ 6 (Думаю в других средах проблем не будет). Дополнительно подключается библиотека th32.lib. Запуск исполняемого модуля прописывается в Автозагрузке. При аварийном вылете Проводника нужно вызвать Task Manager (Ctrl+Alt+Del), найти имя этой программы (как назовете исходный cpp-файл, так и будет) и выбрать "Завершить задачу". Проводник перезапустится. Одновременно будильник также перезапустит и себя. На всякий случай.


[an error occurred while processing this directive]

[an error occurred while processing this directive]